<?php

namespace Fendx\Middleware;

use Fendx\Core\RequestContext;
use Fendx\Di;
use Fendx\Exception\AccessDeniedException;
use Fendx\Request;
use Fendx\Router\Middleware\MiddlewareInterface;
use Fendx\Router\Middleware\RequestHandler;

class PermissionMiddleware implements MiddlewareInterface
{

    public function process(Request $request, RequestHandler $handler)
    {
        $request = Di::factory()->getRequest();

        $options = $request->getOptions();
        $isCheck = true;
        $mapRouterPermissions = [];
        foreach ($options as $option) {
            if (0 === strcmp($option, 'role=off') || 0 === strcmp($option, 'permission=off')) {
                $isCheck = false;
                break;
            }else if (str_starts_with($option, 'role=')) {
                $role = substr($option, 5);
                $mapRouterPermissions[$role] = 1;
            }else if (str_starts_with($option, 'permission=')) {
                $role = substr($option, 11);
                $mapRouterPermissions[$role] = 1;
            }
        }

        if ($isCheck) {
            if (empty($mapRouterPermissions)) {
                throw new AccessDeniedException('No permission', 401);
            }
            // 用户角色
            $arrRoles = RequestContext::get('__roles') ?? RequestContext::get('__user')['roles'] ?? [];
            if (empty($arrRoles)) {
                throw new AccessDeniedException('No permission', 401);
            }
            // 如果是超级管理员则不检查权限
            $isAdmin = in_array('admin', $arrRoles);
            if (!$isAdmin) {
                $isAllow = false;
                foreach ($arrRoles as $role) {
                    if (isset($mapRouterPermissions[$role])) {
                        $isAllow = true;
                        break;
                    }
                }
                if (!$isAllow) {
                    throw new AccessDeniedException('No permission', 401);
                }
            }
        }

        $result = $handler->handle($request);

        return $result;
    }
}
